#include <sys/time.h>
#include <ctime>

#include "Timestamp.h"

namespace Logger
{
    Timestamp Timestamp::now()
    {
        struct timeval tv{};
        // 在x86-64平台gettimeofday()已不是系统调用不会陷入内核, 多次调用不会有性能损失
        ::gettimeofday(&tv, nullptr);
        return Timestamp(tv.tv_sec * sMicroSecondsPerSecond + tv.tv_usec);
    }

    std::string Timestamp::toString() const
    {
        char buf[64]{};
        // tm *tm_time = ::localtime(&this->microSecondsSinceEpoch_);
        tm tm1{};
        ::localtime_r(&this->microSecondsSinceEpoch_, &tm1); // 线程安全
        ::snprintf(buf, sizeof(buf), "%4d/%02d/%02d %02d:%02d:%02d",
                   tm1.tm_year + 1900,
                   tm1.tm_mon + 1,
                   tm1.tm_mday,
                   tm1.tm_hour,
                   tm1.tm_min,
                   tm1.tm_sec);
        return buf;
    }

    // 格式：年月日 星期 时分秒.微秒
    // 2025/07/09 21:46:10
    // 2025/07/09 21:46:10.773804
    std::string Timestamp::toFormattedString(bool showMicroseconds) const
    {
        char buf[64]{};
        // time_t seconds = static_cast<time_t>(this->microSecondsSinceEpoch_ / sMicroSecondsPerSecond);
        // tm *tm_time = ::localtime(&seconds);
        tm tm1{};
        ::localtime_r(&this->microSecondsSinceEpoch_, &tm1); // 线程安全

        if (showMicroseconds)
        {
            int microseconds = static_cast<int>(this->microSecondsSinceEpoch_ % sMicroSecondsPerSecond);
            ::snprintf(buf, sizeof(buf), "%4d/%02d/%02d %02d:%02d:%02d.%06d",
                       tm1.tm_year + 1900,
                       tm1.tm_mon + 1,
                       tm1.tm_mday,
                       tm1.tm_hour,
                       tm1.tm_min,
                       tm1.tm_sec,
                       microseconds);
        }
        else
        {
            ::snprintf(buf, sizeof(buf), "%4d/%02d/%02d %02d:%02d:%02d",
                       tm1.tm_year + 1900,
                       tm1.tm_mon + 1,
                       tm1.tm_mday,
                       tm1.tm_hour,
                       tm1.tm_min,
                       tm1.tm_sec);
        }
        return buf;
    }
} // namespace Logger